home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / UGPRG.ZIP / DENTHOR / TUT10.DOC < prev    next >
Encoding:
Text File  |  1996-07-27  |  30.0 KB  |  886 lines

  1.                    ╒═══════════════════════════════╕
  2.                    │         W E L C O M E         │
  3.                    │  To the VGA Trainer Program   │ │
  4.                    │              By               │ │
  5.                    │      DENTHOR of ASPHYXIA      │ │ │
  6.                    ╘═══════════════════════════════╛ │ │
  7.                      ────────────────────────────────┘ │
  8.                        ────────────────────────────────┘
  9.  
  10.                            --==[ PART 10 ]==--
  11.  
  12.  
  13.  
  14. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  15. ■ Introduction
  16.  
  17. Wow! The trainer has finally reached part 10! This will also be the
  18. first part introduced simultaneously to local BBS's and the INTERNET at
  19. the same time! Yes folks, I put up a copy of previous tutorials onto
  20. various ftp sites, and awaited the flames saying that the net.gurus
  21. already knew this stuff, and why was I wasting disk space! The flames
  22. did not appear (well, except for one), and I got some messages saying
  23. keep it up, so from now on I will upload all future trainers to ftp
  24. sites too (wasp.eng.ufl.edu , cs.uwp.edu etc.). I will also leave a
  25. notice in the USENET groups comp.lang.pascal and comp.sys.ibm.pc.demos
  26. when a new part is finished (Until enough people say stop ;-))
  27.  
  28. I can also be reached at my new E-Mail address,
  29.                  smith9@batis.bis.und.ac.za
  30.  
  31. Well, this tutorial is on Chain-4. When asked to do a trainer on
  32. Chain-4, I felt that I would be walking on much travelled ground (I have
  33. seen numerous trainers on the subject), but the people who asked me said
  34. that they hadn't seen any, so could I do one anyway? Who am I to say no?
  35.  
  36. The sample program attached isn't that great, but I am sure that all you
  37. people out there can immediately see the potential that Chain-4 holds.
  38.  
  39.  
  40. If you would like to contact me, or the team, there are many ways you
  41. can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
  42.                   on the ASPHYXIA BBS.
  43.             2) Write to Denthor, EzE or Goth on Connectix.
  44.             3) Write to :  Grant Smith
  45.                            P.O.Box 270 Kloof
  46.                            3640
  47.                            Natal
  48.                            South Africa
  49.             4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
  50.                   call during varsity). Call +27-31-73-2129 if you call
  51.                   from outside South Africa. (It's YOUR phone bill ;-))
  52.             5) Write to smith9@batis.bis.und.ac.za in E-Mail.
  53.  
  54. NB : If you are a representative of a company or BBS, and want ASPHYXIA
  55.        to do you a demo, leave mail to me; we can discuss it.
  56. NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
  57.         quite lonely and want to meet/help out/exchange code with other demo
  58.         groups. What do you have to lose? Leave a message here and we can work
  59.         out how to transfer it. We really want to hear from you!
  60.  
  61.  
  62.  
  63. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  64. ■ What is Chain-4?
  65.  
  66. You people out there all have at least 256k vga cards. Most of you have
  67. 512k vga cards, and some have 1MB vga cards. But what you see on your
  68. screen, as discussed in previous trainers, is 64k of data! What happened
  69. to the other 192k??? Chain-4 is a method of using all 256k at one time.
  70.  
  71. The way this is done is simple. 1 screen = 64k. 64k * 4 = 256k.
  72. Therefore, chain-4 allows you to write to four screens, while displaying
  73. one of them. You can then move around these four screens to see the data
  74. on them. Think of the Chain-4 screen as a big canvas. The viewport,
  75. the bit you see out of, is a smaller rectangle which can be anywhere
  76. over the bigger canvas.
  77.  
  78.      +----------------------------+ Chain-4 screen
  79.      |          +--+              |
  80.      |          |  | <- Viewport  |
  81.      |          +--+              |
  82.      |                            |
  83.      +----------------------------+
  84.  
  85.  
  86. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  87. ■ The size of the chain-4 screen
  88.  
  89. The Chain-4 screen, can be any size that adds up to 4 screens.
  90.  
  91. For example, it can be 4 screens across and one screen down, or one
  92. screen across and 4 screens down, or two screens across and two screens
  93. down, and any size in between.
  94.  
  95. In the sample program, the size is a constant. The size * 8 is how many
  96. pixels across there are on the chain-4 screen, ie
  97.    Size = 40   = 320 pixels across = 1 screen across, 4 screens down
  98.    Size = 80   = 640 pixels across = 2 screens across, 2 screens down
  99. etc.
  100.  
  101. We need to know the size of the screen for almost all dealings with the
  102. Chain-4 screen, for obvious reasons.
  103.  
  104.  
  105. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  106. ■ Layout of the chain-4 screen, and accessing it
  107.  
  108. If you will remember all the way back to Part 1 of this series, I
  109. explained that the memory layout of the MCGA screen is linear. Ie, the
  110. top left hand pixel was pixel zero, the one to the right of it was
  111. number one, the next one was number two etc. With Chain-4, things are
  112. very different.
  113.  
  114. Chain-4 gets the 4 screens and chains them together (hence the name :)).
  115. Each screen has a different plane value, and must be accessed
  116. differently. The reason for this is that a segment of memory is only 64k
  117. big, so that we could not fit the entire Chain-4 screen into one
  118. segment.
  119.  
  120. All Chain-4 screens are accessed from $a000, just like in MCGA mode.
  121. What we do is, before we write to the screen, find out what plane we are
  122. writing to, set that plane, then plot the pixel. Here is how we find out
  123. how far in to plot the pixel and what plane it is on :
  124.  
  125.  Instead of the linear model of MCGA mode, ie :
  126.         ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  127.         │00│01│02│03│04│05│06│07│08│09│10│11│ ...
  128.  
  129.  Each plane of the Chain-4 screen accesses the memory in this way :
  130.  
  131.        Plane 0 :
  132.         ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  133.         │00│  │  │  │01│  │  │  │02│  │  │  │ ...
  134.  
  135.        Plane 1 :
  136.         ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  137.         │  │00│  │  │  │01│  │  │  │02│  │  │ ...
  138.  
  139.        Plane 2 :
  140.         ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  141.         │  │  │00│  │  │  │01│  │  │  │02│  │ ...
  142.  
  143.        Plane 3 :
  144.         ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  145.         │  │  │  │00│  │  │  │01│  │  │  │02│ ...
  146.  
  147. In this way, by choosing the right plane to write to, we can access all
  148. of the 256k of memory available to us. The plane that we write to can
  149. easily be found by the simple calculation of  x mod 4, and the x
  150. coordinate is also found by  x div 4. We work out our y by multiplying
  151. it by the size of our chain-4 screen.
  152.  
  153. NOTE : It is possible to write to all four planes at once by setting the
  154.        correct port values.
  155.  
  156. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  157. ■ Uses of Chain-4
  158.  
  159. The uses of Chain-4 are many. One could write data to one screen, then
  160. flip to it (the move_to command is almost instantaneous). This means
  161. that 64k of memory does not need to be set aside for a virtual screen,
  162. you are using the vga cards memory instead!
  163.  
  164. Scrolling is much easier to code for in Chain-4 mode.
  165.  
  166. It is possible to "tweak" the mode into other resolutions. In our demo,
  167. our vectors were in 320x240 mode, and our dot vectors were in 320x400
  168. mode.
  169.  
  170. The main disadvantage of chain-4 as I see it is the plane swapping,
  171. which can be slow. With a bit of clever coding however, these can be
  172. kept down to a minimum.
  173.  
  174. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  175. ■ The sample programs
  176.  
  177. The first sample program is GFX.PAS. This is a until in which I have
  178. placed most of our routines from previous tuts. All the procedures and
  179. variables you can see under the INTERFACE section can be used in any
  180. program with GFX in the USES clause. In other words, I could do this :
  181.  
  182. USES GFX,crt;
  183.  
  184. BEGIN
  185.   Setupvirtual;
  186.   cls (vaddr,0);
  187.   Shutdown;
  188. END.
  189.  
  190. This program would compile perfectly. What I suggest you do is this :
  191. Rename the file to a name that suites you (eg your group name), change
  192. the first line of the unit to that name, then add all useful procedures
  193. etc. to the unit. Make it grow :-).
  194.  
  195. The second file is the sample program (note the USES GFX,crt; up near
  196. the top!). The program is easy to understand and is documented. The bit
  197. that I want to draw your attention to is the constant, BIT. Because I
  198. am distributing this file to many places in text form, not binary form,
  199. I could not just add a .CEL file with the program. So what I did was
  200. write some text in one color then saved it as a .CEL . I then wrote a
  201. ten line program that did the following : Moving from left to right, it
  202. counted how many pixels were of color zero, then saved the byte value to
  203. an array. When it came across color one, is counted for how long that
  204. went on then saved the byte value and saved it to an array and so on.
  205. When it was finished, I converted the array into a text file in the
  206. CONST format. Not too cunning, but I thought I had better explain it ;-)
  207.  
  208. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  209. ■ In closing
  210.  
  211. There are other documents and sample programs available on Chain-4 and
  212. it's like : Try XLIB for one...
  213.  
  214. Finally! Some BBS's have joined my BBS list! (Okay, only two new ones,
  215. but it's a start ;-)) All you international BBS's! If you will regularly
  216. download the tuts from an FTP site, give me your names!
  217.  
  218. I own a car. The car's name is Bob. A few days ago, Bob was in an
  219. accident, and now has major damage to his front. Knowing insurance, I
  220. probably won't get much, probably nothing (the other guy wasn't insured,
  221. and I am only 18 :( ). I will probably have to find work in order to pay
  222. for my repairs. The point to this meandering is this : I am upset, so if
  223. you think you are getting a quote, you can just forget it.
  224.  
  225. Oh, well. Life goes on!
  226.  
  227. See you next time,
  228.   - Denthor
  229.  
  230. These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
  231.  
  232. ╔══════════════════════════╦════════════════╦═════╦═══╦════╦════╗
  233. ║BBS Name                  ║Telephone No.   ║Open ║Msg║File║Past║
  234. ╠══════════════════════════╬════════════════╬═════╬═══╬════╬════╣
  235. ║ASPHYXIA BBS #1           ║(031) 765-5312  ║ALL  ║ * ║ *  ║ *  ║
  236. ║ASPHYXIA BBS #2           ║(031) 765-6293  ║ALL  ║ * ║ *  ║ *  ║
  237. ║Connectix BBS             ║(031) 266-9992  ║ALL  ║   ║ *  ║ *  ║
  238. ║POP!                      ║(012) 661-1257  ║ALL  ║   ║ *  ║ *  ║
  239. ║Pure Surf BBS             ║(031) 561-5943  ║A/H  ║   ║ *  ║ *  ║
  240. ╚══════════════════════════╩════════════════╩═════╩═══╩════╩════╝
  241.  
  242. For international users : If you live outside the Republic of South
  243. Africa, do the following : Dial +27, dont dial the first 0, but dial
  244. the rest of the number. Eg, for the ASPHYXIA BBS : +27-31-765-5312
  245.  
  246. Open = Open at all times or only A/H
  247. Msg  = Available in message base
  248. File = Available in file base
  249. Past = Previous Parts available
  250.  
  251. Unit GFX;
  252.  
  253.  
  254. INTERFACE
  255.  
  256. USES crt;
  257. CONST VGA = $A000;
  258.  
  259. TYPE Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
  260.      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  261.  
  262. VAR Virscr : VirtPtr;                     { Our first Virtual screen }
  263.     Vaddr  : word;                        { The segment of our virtual screen}
  264.  
  265. Procedure SetMCGA;
  266.    { This procedure gets you into 320x200x256 mode. }
  267. Procedure SetText;
  268.    { This procedure returns you to text mode.  }
  269. Procedure Cls (Where:word;Col : Byte);
  270.    { This clears the screen to the specified color }
  271. Procedure SetUpVirtual;
  272.    { This sets up the memory needed for the virtual screen }
  273. Procedure ShutDown;
  274.    { This frees the memory used by the virtual screen }
  275. procedure flip(source,dest:Word);
  276.    { This copies the entire screen at "source" to destination }
  277. Procedure Pal(Col,R,G,B : Byte);
  278.    { This sets the Red, Green and Blue values of a certain color }
  279. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  280.   { This gets the Red, Green and Blue values of a certain color }
  281. procedure WaitRetrace;
  282.    {  This waits for a vertical retrace to reduce snow on the screen }
  283. Procedure Hline (x1,x2,y:word;col:byte;where:word);
  284.    { This draws a horizontal line from x1 to x2 on line y in color col }
  285. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  286.   { This draws a solid line from a,b to c,d in colour col }
  287. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  288.    { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  289.      in color col }
  290. Function rad (theta : real) : real;
  291.    {  This calculates the degrees of an angle }
  292. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  293.    { This puts a pixel on the screen by writing directly to memory. }
  294. Function Getpixel (X,Y : Integer; where:word) :Byte;
  295.    { This gets the pixel on the screen by reading directly to memory. }
  296.  
  297.  
  298. IMPLEMENTATION
  299.  
  300. {──────────────────────────────────────────────────────────────────────────}
  301. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  302. BEGIN
  303.   asm
  304.      mov        ax,0013h
  305.      int        10h
  306.   end;
  307. END;
  308.  
  309. {──────────────────────────────────────────────────────────────────────────}
  310. Procedure SetText;  { This procedure returns you to text mode.  }
  311. BEGIN
  312.   asm
  313.      mov        ax,0003h
  314.      int        10h
  315.   end;
  316. END;
  317.  
  318. {──────────────────────────────────────────────────────────────────────────}
  319. Procedure Cls (Where:word;Col : Byte); assembler;
  320.    { This clears the screen to the specified color }
  321. asm
  322.    push    es
  323.    mov     cx, 32000;
  324.    mov     es,[where]
  325.    xor     di,di
  326.    mov     al,[col]
  327.    mov     ah,al
  328.    rep     stosw
  329.    pop     es
  330. End;
  331.  
  332. {──────────────────────────────────────────────────────────────────────────}
  333. Procedure SetUpVirtual;
  334.    { This sets up the memory needed for the virtual screen }
  335. BEGIN
  336.   GetMem (VirScr,64000);
  337.   vaddr := seg (virscr^);
  338. END;
  339.  
  340. {──────────────────────────────────────────────────────────────────────────}
  341. Procedure ShutDown;
  342.    { This frees the memory used by the virtual screen }
  343. BEGIN
  344.   FreeMem (VirScr,64000);
  345. END;
  346.  
  347. {──────────────────────────────────────────────────────────────────────────}
  348. procedure flip(source,dest:Word); assembler;
  349.   { This copies the entire screen at "source" to destination }
  350. asm
  351.   push    ds
  352.   mov     ax, [Dest]
  353.   mov     es, ax
  354.   mov     ax, [Source]
  355.   mov     ds, ax
  356.   xor     si, si
  357.   xor     di, di
  358.   mov     cx, 32000
  359.   rep     movsw
  360.   pop     ds
  361. end;
  362.  
  363. {──────────────────────────────────────────────────────────────────────────}
  364. Procedure Pal(Col,R,G,B : Byte); assembler;
  365.   { This sets the Red, Green and Blue values of a certain color }
  366. asm
  367.    mov    dx,3c8h
  368.    mov    al,[col]
  369.    out    dx,al
  370.    inc    dx
  371.    mov    al,[r]
  372.    out    dx,al
  373.    mov    al,[g]
  374.    out    dx,al
  375.    mov    al,[b]
  376.    out    dx,al
  377. end;
  378.  
  379. {──────────────────────────────────────────────────────────────────────────}
  380. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  381.   { This gets the Red, Green and Blue values of a certain color }
  382. Var
  383.    rr,gg,bb : Byte;
  384. Begin
  385.    asm
  386.       mov    dx,3c7h
  387.       mov    al,col
  388.       out    dx,al
  389.  
  390.       add    dx,2
  391.  
  392.       in     al,dx
  393.       mov    [rr],al
  394.       in     al,dx
  395.       mov    [gg],al
  396.       in     al,dx
  397.       mov    [bb],al
  398.    end;
  399.    r := rr;
  400.    g := gg;
  401.    b := bb;
  402. end;
  403.  
  404. {──────────────────────────────────────────────────────────────────────────}
  405. procedure WaitRetrace; assembler;
  406.   {  This waits for a vertical retrace to reduce snow on the screen }
  407. label
  408.   l1, l2;
  409. asm
  410.     mov dx,3DAh
  411. l1:
  412.     in al,dx
  413.     and al,08h
  414.     jnz l1
  415. l2:
  416.     in al,dx
  417.     and al,08h
  418.     jz  l2
  419. end;
  420.  
  421. {──────────────────────────────────────────────────────────────────────────}
  422. Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  423.   { This draws a horizontal line from x1 to x2 on line y in color col }
  424. asm
  425.   mov   ax,where
  426.   mov   es,ax
  427.   mov   ax,y
  428.   mov   di,ax
  429.   shl   ax,8
  430.   shl   di,6
  431.   add   di,ax
  432.   add   di,x1
  433.  
  434.   mov   al,col
  435.   mov   ah,al
  436.   mov   cx,x2
  437.   sub   cx,x1
  438.   shr   cx,1
  439.   jnc   @start
  440.   stosb
  441. @Start :
  442.   rep   stosw
  443. end;
  444.  
  445. {──────────────────────────────────────────────────────────────────────────}
  446. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  447.   { This draws a solid line from a,b to c,d in colour col }
  448.   function sgn(a:real):integer;
  449.   begin
  450.        if a>0 then sgn:=+1;
  451.        if a<0 then sgn:=-1;
  452.        if a=0 then sgn:=0;
  453.   end;
  454. var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
  455. begin
  456.      u:= c - a;
  457.      v:= d - b;
  458.      d1x:= SGN(u);
  459.      d1y:= SGN(v);
  460.      d2x:= SGN(u);
  461.      d2y:= 0;
  462.      m:= ABS(u);
  463.      n := ABS(v);
  464.      IF NOT (M>N) then
  465.      BEGIN
  466.           d2x := 0 ;
  467.           d2y := SGN(v);
  468.           m := ABS(v);
  469.           n := ABS(u);
  470.      END;
  471.      s := m shr 1;
  472.      FOR i := 0 TO m DO
  473.      BEGIN
  474.           putpixel(a,b,col,where);
  475.           s := s + n;
  476.           IF not (s<m) THEN
  477.           BEGIN
  478.                s := s - m;
  479.                a:= a + d1x;
  480.                b := b + d1y;
  481.           END
  482.           ELSE
  483.           BEGIN
  484.                a := a + d2x;
  485.                b := b + d2y;
  486.           END;
  487.      end;
  488. END;
  489.  
  490.  
  491. {──────────────────────────────────────────────────────────────────────────}
  492. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  493.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  494.     in color col }
  495. var
  496.   x:integer;
  497.   mny,mxy:integer;
  498.   mnx,mxx,yc:integer;
  499.   mul1,div1,
  500.   mul2,div2,
  501.   mul3,div3,
  502.   mul4,div4:integer;
  503.  
  504. begin
  505.   mny:=y1; mxy:=y1;
  506.   if y2<mny then mny:=y2;
  507.   if y2>mxy then mxy:=y2;
  508.   if y3<mny then mny:=y3;
  509.   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  510.   if y4<mny then mny:=y4;
  511.   if y4>mxy then mxy:=y4;
  512.  
  513.   if mny<0 then mny:=0;
  514.   if mxy>199 then mxy:=199;
  515.   if mny>199 then exit;
  516.   if mxy<0 then exit;        { Verticle range checking }
  517.  
  518.   mul1:=x1-x4; div1:=y1-y4;
  519.   mul2:=x2-x1; div2:=y2-y1;
  520.   mul3:=x3-x2; div3:=y3-y2;
  521.   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }
  522.  
  523.   for yc:=mny to mxy do
  524.     begin
  525.       mnx:=320;
  526.       mxx:=-1;
  527.       if (y4>=yc) or (y1>=yc) then
  528.         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
  529.           if not(y4=y1) then
  530.             begin
  531.               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
  532.               if x<mnx then
  533.                 mnx:=x;
  534.               if x>mxx then
  535.                 mxx:=x;       { Set point as start or end of horiz line }
  536.             end;
  537.       if (y1>=yc) or (y2>=yc) then
  538.         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
  539.           if not(y1=y2) then
  540.             begin
  541.               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
  542.               if x<mnx then
  543.                 mnx:=x;
  544.               if x>mxx then
  545.                 mxx:=x;       { Set point as start or end of horiz line }
  546.             end;
  547.       if (y2>=yc) or (y3>=yc) then
  548.         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
  549.           if not(y2=y3) then
  550.             begin
  551.               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
  552.               if x<mnx then
  553.                 mnx:=x;
  554.               if x>mxx then
  555.                 mxx:=x;       { Set point as start or end of horiz line }
  556.             end;
  557.       if (y3>=yc) or (y4>=yc) then
  558.         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
  559.           if not(y3=y4) then
  560.             begin
  561.               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
  562.               if x<mnx then
  563.                 mnx:=x;
  564.               if x>mxx then
  565.                 mxx:=x;       { Set point as start or end of horiz line }
  566.             end;
  567.       if mnx<0 then
  568.         mnx:=0;
  569.       if mxx>319 then
  570.         mxx:=319;          { Range checking on horizontal line }
  571.       if mnx<=mxx then
  572.         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
  573.     end;
  574.   end;
  575.  
  576. {──────────────────────────────────────────────────────────────────────────}
  577. Function rad (theta : real) : real;
  578.   {  This calculates the degrees of an angle }
  579. BEGIN
  580.   rad := theta * pi / 180
  581. END;
  582.  
  583. {──────────────────────────────────────────────────────────────────────────}
  584. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
  585.   { This puts a pixel on the screen by writing directly to memory. }
  586. Asm
  587.   mov     ax,[where]
  588.   mov     es,ax
  589.   mov     bx,[X]
  590.   mov     dx,[Y]
  591.   mov     di,bx
  592.   mov     bx, dx                  {; bx = dx}
  593.   shl     dx, 8
  594.   shl     bx, 6
  595.   add     dx, bx                  {; dx = dx + bx (ie y*320)}
  596.   add     di, dx                  {; finalise location}
  597.   mov     al, [Col]
  598.   stosb
  599. End;
  600.  
  601. {──────────────────────────────────────────────────────────────────────────}
  602. Function Getpixel (X,Y : Integer; where:word):byte; assembler;
  603.   { This puts a pixel on the screen by writing directly to memory. }
  604. Asm
  605.   mov     ax,[where]
  606.   mov     es,ax
  607.   mov     bx,[X]
  608.   mov     dx,[Y]
  609.   mov     di,bx
  610.   mov     bx, dx                  {; bx = dx}
  611.   shl     dx, 8
  612.   shl     bx, 6
  613.   add     dx, bx                  {; dx = dx + bx (ie y*320)}
  614.   add     di, dx                  {; finalise location}
  615.   lodsb
  616. End;
  617.  
  618. {──────────────────────────────────────────────────────────────────────────}
  619. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  620.   { This loads the cel 'filename' into the pointer scrptr }
  621. var
  622.   Fil : file;
  623.   Buf : array [1..1024] of byte;
  624.   BlocksRead, Count : word;
  625. begin
  626.   assign (Fil, FileName);
  627.   reset (Fil, 1);
  628.   BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
  629.   Count := 0; BlocksRead := $FFFF;
  630.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  631.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  632.     Count := Count + 1024;
  633.   end;
  634.   close (Fil);
  635. end;
  636.  
  637.  
  638. BEGIN
  639. END.Uses Crt,GFX;
  640.  
  641. Const Size : Byte = 80;      { Size =  40 = 1 across, 4 down }
  642.                              { Size =  80 = 2 across, 2 down }
  643.                              { Size = 160 = 4 across, 1 down }
  644.  
  645.       bit : Array [1..897] of byte = (
  646. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,2,151,5,149,6,148,7,147,8,49,2,95,8,49,
  647. 4,93,9,49,3,93,4,2,3,49,4,92,4,3,3,48,4,92,4,3,4,48,4,91,4,4,3,48,4,92,4,3,4,
  648. 48,3,58,2,32,4,4,4,47,4,57,3,31,4,5,3,48,3,57,4,30,4,5,4,47,3,57,5,29,4,6,4,46,
  649. 4,57,4,29,4,7,3,47,3,58,2,30,4,7,4,46,4,90,4,7,4,46,3,90,4,8,4,27,2,16,3,90,4,
  650. 8,9,22,3,16,3,89,4,5,13,8,6,8,3,15,3,90,4,2,15,6,10,6,3,16,3,6,1,21,1,9,2,7,1,
  651. 21,6,14,18,9,5,2,4,5,4,1,4,10,3,4,5,10,2,7,3,8,2,5,3,9,3,7,8,13,13,1,4,9,4,5,3,
  652. 5,3,1,6,9,3,3,6,9,4,5,4,8,3,3,4,9,3,6,9,11,10,6,4,8,4,6,3,4,11,8,3,2,7,9,5,4,4,
  653. 9,3,2,4,9,3,6,4,4,2,8,10,9,4,7,4,6,3,5,5,3,3,8,3,1,8,8,5,4,5,8,3,3,3,9,4,5,4,5,
  654. 2,5,10,12,4,7,3,5,5,4,5,4,3,7,3,1,4,1,3,9,4,5,4,9,3,2,3,10,3,6,3,5,3,4,10,13,3,
  655. 8,3,2,7,5,4,5,3,7,7,1,3,9,4,5,5,9,3,1,3,10,3,6,3,5,4,4,5,1,4,12,4,8,3,2,5,6,4,
  656. 5,4,6,6,2,4,8,4,5,5,10,6,10,4,5,4,5,3,5,2,3,4,13,4,8,3,3,1,9,3,6,3,7,5,3,3,5,1,
  657. 3,3,5,5,4,2,5,5,11,3,6,3,5,4,10,3,14,4,8,3,12,3,6,4,6,5,3,3,5,2,2,4,4,6,4,2,5,
  658. 5,6,1,3,4,5,3,6,3,10,4,14,4,5,1,2,4,11,3,6,3,7,5,3,3,4,3,1,4,4,6,4,3,5,4,6,2,3,
  659. 3,6,3,5,4,9,4,15,3,5,2,3,4,9,3,6,4,7,4,3,3,5,2,2,3,4,7,3,3,6,3,6,3,2,4,5,4,5,3,
  660. 10,3,15,4,4,3,4,3,9,3,6,3,7,4,4,3,4,3,1,4,3,3,1,3,3,3,6,4,6,2,3,3,6,3,5,4,9,4,
  661. 15,4,4,3,4,4,7,3,6,4,7,4,3,3,4,3,2,3,3,3,2,3,2,4,5,5,5,3,2,4,6,3,5,4,8,4,16,4,
  662. 4,2,6,3,7,3,5,4,7,4,4,3,3,3,3,8,2,3,2,4,5,6,4,3,3,3,7,3,4,5,8,4,16,4,4,2,6,3,6,
  663. 3,5,4,8,3,5,8,3,9,2,3,1,4,6,6,3,3,4,3,7,3,3,6,7,4,17,4,4,3,5,3,6,3,4,4,9,3,5,8,
  664. 3,7,3,8,6,3,1,4,1,4,3,4,7,3,2,3,1,3,7,4,17,4,4,3,5,3,5,11,9,3,6,7,4,6,4,7,6,3,
  665. 2,8,4,3,8,7,2,3,6,4,18,3,5,4,3,4,5,10,10,3,6,6,6,4,4,6,7,3,4,6,5,3,8,7,2,4,4,4,
  666. 19,3,5,10,5,3,1,6,11,3,7,3,16,5,7,4,4,5,6,3,8,6,3,5,3,4,19,3,6,9,5,3,18,2,25,5,
  667. 9,3,6,3,7,2,10,3,6,4,3,3,20,3,8,5,6,3,44,6,10,2,39,3,3,2,22,2,19,3,43,7,101,3,
  668. 42,8,102,3,41,4,1,4,101,4,39,5,2,3,102,3,39,4,4,3,102,3,38,4,4,4,101,3,38,4,5,
  669. 3,102,3,37,4,5,4,101,4,36,4,6,3,102,3,37,3,6,4,102,3,36,4,6,3,102,3,37,3,6,3,
  670. 103,3,37,3,5,4,102,4,37,3,4,4,103,3,38,10,104,3,38,9,105,2,40,7,106,2,41,4,0);
  671.  
  672.  
  673. {──────────────────────────────────────────────────────────────────────────}
  674. Procedure InitChain4; ASSEMBLER;
  675.   {  This procedure gets you into Chain 4 mode }
  676. Asm
  677.     mov    ax, 13h
  678.     int    10h         { Get into MCGA Mode }
  679.  
  680.     mov    dx, 3c4h    { Port 3c4h = Sequencer Address Register }
  681.     mov    al, 4       { Index 4 = memory mode }
  682.     out    dx, al
  683.     inc    dx          { Port 3c5h ... here we set the mem mode }
  684.     in     al, dx
  685.     and    al, not 08h
  686.     or     al, 04h
  687.     out    dx, al
  688.     mov    dx, 3ceh
  689.     mov    al, 5
  690.     out    dx, al
  691.     inc    dx
  692.     in     al, dx
  693.     and    al, not 10h
  694.     out    dx, al
  695.     dec    dx
  696.     mov    al, 6
  697.     out    dx, al
  698.     inc    dx
  699.     in     al, dx
  700.     and    al, not 02h
  701.     out    dx, al
  702.     mov    dx, 3c4h
  703.     mov    ax, (0fh shl 8) + 2
  704.     out    dx, ax
  705.     mov    ax, 0a000h
  706.     mov    es, ax
  707.     sub    di, di
  708.     mov    ax, 0000h {8080h}
  709.     mov    cx, 32768
  710.     cld
  711.     rep    stosw            { Clear garbage off the screen ... }
  712.  
  713.     mov    dx, 3d4h
  714.     mov    al, 14h
  715.     out    dx, al
  716.     inc    dx
  717.     in     al, dx
  718.     and    al, not 40h
  719.     out    dx, al
  720.     dec    dx
  721.     mov    al, 17h
  722.     out    dx, al
  723.     inc    dx
  724.     in     al, dx
  725.     or     al, 40h
  726.     out    dx, al
  727.  
  728.     mov    dx, 3d4h
  729.     mov    al, 13h
  730.     out    dx, al
  731.     inc    dx
  732.     mov    al, [Size]      { Size * 8 = Pixels across. Only 320 are visible}
  733.     out    dx, al
  734. End;
  735.  
  736.  
  737. {──────────────────────────────────────────────────────────────────────────}
  738. Procedure C4PutPixel(X,Y : Word; Col : Byte); ASSEMBLER;
  739.   { This puts a pixel on the chain 4 screen }
  740. Asm
  741.     mov    ax,[y]
  742.     xor    bx,bx
  743.     mov    bl,[size]
  744.     imul   bx
  745.     shl    ax,1
  746.     mov    bx,ax
  747.     mov    ax, [X]
  748.     mov    cx, ax
  749.     shr    ax, 2
  750.     add    bx, ax
  751.     and    cx, 00000011b
  752.     mov    ah, 1
  753.     shl    ah, cl
  754.     mov    dx, 3c4h                  { Sequencer Register    }
  755.     mov    al, 2                     { Map Mask Index        }
  756.     out    dx, ax
  757.  
  758.     mov    ax, 0a000h
  759.     mov    es, ax
  760.     mov    al, [col]
  761.     mov    es: [bx], al
  762. End;
  763.  
  764. {──────────────────────────────────────────────────────────────────────────}
  765. Procedure Plane(Which : Byte); ASSEMBLER;
  766.   { This sets the plane to write to in Chain 4}
  767. Asm
  768.    mov     al, 2h
  769.    mov     ah, 1
  770.    mov     cl, [Which]
  771.    shl     ah, cl
  772.    mov     dx, 3c4h                  { Sequencer Register    }
  773.    out     dx, ax
  774. End;
  775.  
  776.  
  777. {──────────────────────────────────────────────────────────────────────────}
  778. procedure moveto(x, y : word);
  779.   { This moves to position x*4,y on a chain 4 screen }
  780. var o : word;
  781. begin
  782.   o := y*size*2+x;
  783.   asm
  784.     mov    bx, [o]
  785.     mov    ah, bh
  786.     mov    al, 0ch
  787.  
  788.     mov    dx, 3d4h
  789.     out    dx, ax
  790.  
  791.     mov    ah, bl
  792.     mov    al, 0dh
  793.     mov    dx, 3d4h
  794.     out    dx, ax
  795.   end;
  796. end;
  797.  
  798.  
  799.  
  800. {──────────────────────────────────────────────────────────────────────────}
  801. Procedure Putpic (x,y:integer);
  802.   { This put's the picture at coordinates x,y on the chain-4 screen }
  803. Var loop1,loop2:integer;
  804.     depth,cur:integer;
  805. BEGIN
  806.    depth:=1;
  807.    cur:=0;
  808.    For loop1:=1 to 897 do BEGIN
  809.      for loop2:=1 to bit [loop1] do BEGIN
  810.        if cur<>0 then c4putpixel ((depth mod 155)+x,(depth div 155)+y,depth div 155);
  811.        inc (depth);
  812.      END;
  813.      cur:=(cur+1) mod 2;
  814.    END;
  815. END;
  816.  
  817.  
  818. Procedure Play;
  819. Var loop1,loop2:integer;
  820.     xpos,ypos,xdir,ydir:integer;
  821.     ch:char;
  822. Begin
  823.    for loop1:=1 to 62 do
  824.      pal (loop1,loop1,0,62-loop1); { This sets up the pallette for the pic }
  825.  
  826.    MoveTo(0,0); { This moves the view to the top left hand corner }
  827.  
  828.    for loop1:=0 to 3 do
  829.      for loop2:=0 to 5 do
  830.        putpic (loop1*160,loop2*66); { This places the picture all over the
  831.                                       chain-4 screen }
  832.    readkey;
  833.    ch:=#0;
  834.    xpos:=random (78)+1;
  835.    ypos:=random (198)+1; { Random start positions for the view }
  836.    xdir:=1;
  837.    ydir:=1;
  838.    repeat
  839.      moveto (xpos,ypos);
  840.      waitretrace;          { Take this out and watch the screen go crazy! }
  841.      xpos:=xpos+xdir;
  842.      ypos:=ypos+ydir;
  843.      if (xpos>79) or (xpos<1) then xdir:=-xdir;
  844.      if (ypos>199) or (ypos<1) then ydir:=-ydir;  { Hit a boundry, change
  845.                                                     direction! }
  846.      if keypressed then ch:=readkey;
  847.    until ch=#27;  { Quit when escape is pressed }
  848. End;
  849.  
  850.  
  851. BEGIN
  852.   clrscr;
  853.   writeln ('Hello there! Here is the tenth tutorial, on Chain-4! You will notice');
  854.   writeln ('that there are two pascal files here : one is a unit containing all');
  855.   writeln ('our base graphics routines, and one is the demo program.');
  856.   writeln;
  857.   writeln ('In the demo program, we will do the necessary port stuff to get into');
  858.   writeln ('Chain-4. Once in Chain-4 mode, I will put down text saying ASPHYXIA');
  859.   writeln ('over the entire screen. After a key is pressed, the viewport will');
  860.   writeln ('bounce around, displaying the entire Chain-4 screen. The program will');
  861.   writeln ('end when [ESC] is pressed. The code here is really basic (except for');
  862.   writeln ('those port values), and should be very easy to understand.');
  863.   writeln;
  864.   writeln;
  865.   Write ('  Hit any key to contine ...');
  866.   Readkey;
  867.   initChain4;
  868.   play;
  869.   SetText;
  870.   Writeln ('All done. This concludes the tenth sample program in the ASPHYXIA');
  871.   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
  872.   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
  873.   Writeln ('Connectix BBS user, and occasionally read RSAProg. E-mail me at :');
  874.   Writeln ('    smith9@batis.bis.und.ac.za');
  875.   Writeln ('The numbers are available in the main text. You may also write to me at:');
  876.   Writeln ('             Grant Smith');
  877.   Writeln ('             P.O. Box 270');
  878.   Writeln ('             Kloof');
  879.   Writeln ('             3640');
  880.   Writeln ('             Natal');
  881.   Writeln ('             South Africa');
  882.   Writeln ('I hope to hear from you soon!');
  883.   Writeln; Writeln;
  884.   Write   ('Hit any key to exit ...');
  885.   Readkey;
  886. END.